package com.tinyengine.it.controller.db;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tinyengine.it.common.base.Result;
import com.tinyengine.it.common.utils.TableGeneratorUtils;
import com.tinyengine.it.model.entity.ApiGatewayService;
import com.tinyengine.it.model.entity.DbLogicalInfo;
import com.tinyengine.it.model.entity.DbTableFieldsInfo;
import com.tinyengine.it.model.entity.DbTableInfo;
import com.tinyengine.it.model.vo.DbSummaryInfoVo;
import com.tinyengine.it.model.vo.DbTableInfoVo;
import com.tinyengine.it.service.db.DbLogicalInfoService;
import com.tinyengine.it.service.db.DbTableFieldsInfoService;
import com.tinyengine.it.service.db.DbTableInfoService;
import com.tinyengine.it.service.endpoint.ApiDirectoryService;
import com.tinyengine.it.service.endpoint.ApiGatewayServiceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/table-info/api")
@Tag(name = "数据库表维护")
@Validated
@RequiredArgsConstructor
public class DbTableInfoController {

    private final DbTableInfoService dbTableInfoService;
    private final ApiGatewayServiceService apiGatewayServiceService;
    private final DbTableFieldsInfoService dbTableFieldsInfoService;
    private final DbLogicalInfoService dbLogicalInfoService;
    private final ApiDirectoryService apiDirectoryService;

    @Operation(summary = "获取表服务、表",
            parameters = {
                    //@Parameter(name = "serviceId", description = "服务ID")
            },
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = DbTableInfoVo.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/getBasicInfoByServiceId")
    public Result<List<DbSummaryInfoVo>> getBasicInfoByServiceId(@RequestHeader(required = false) Integer appId) {
        LambdaQueryWrapper<ApiGatewayService> lambdaQuery = Wrappers.lambdaQuery();
        if (ObjUtil.isNotNull(appId)) {
            lambdaQuery.eq(ApiGatewayService::getAppId, appId);
        }
        List<ApiGatewayService> serviceList = apiGatewayServiceService.list(lambdaQuery);
        List<DbSummaryInfoVo> root = serviceList.stream().map(gatewayService -> new DbSummaryInfoVo().setId(gatewayService.getId())
                .setDescription(gatewayService.getDescription())
                .setCode(gatewayService.getServiceEn())
                .setParentId(0)
                .setName(gatewayService.getServiceName())).collect(Collectors.toList());

        LambdaQueryWrapper<DbTableInfo> lambdaQueryApiGateway = Wrappers.lambdaQuery();
        if (ObjUtil.isNotNull(appId)) {
            lambdaQueryApiGateway.eq(DbTableInfo::getAppId, appId);
        }
        List<DbTableInfo> tableInfoList = dbTableInfoService.list(lambdaQueryApiGateway);


        LambdaQueryWrapper<DbLogicalInfo> lambdaQueryTable = Wrappers.lambdaQuery();
        if (ObjUtil.isNotNull(appId)) {
            lambdaQueryTable.eq(DbLogicalInfo::getAppId, appId);
        }
        List<DbLogicalInfo> logicalInfos = dbLogicalInfoService.list(lambdaQueryTable);

        root.forEach(service -> {
            List<DbTableInfo> tableInfos = tableInfoList.stream().filter(f -> f.getServiceId().equals(service.getId())).collect(Collectors.toList());
            service.setTable(tableInfos.stream().map(m -> new DbSummaryInfoVo()
                    .setId(m.getId())
                    .setCode(m.getName())
                    .setName(m.getNameCh())
                    .setParentId(service.getId())
            ).collect(Collectors.toList()));

            List<DbLogicalInfo> logTableInfos = logicalInfos.stream().filter(f -> f.getServiceId().equals(service.getId())).collect(Collectors.toList());

            service.setLogTable(logTableInfos.stream().map(m -> new DbSummaryInfoVo()
                    .setId(m.getId())
                    .setParentId(service.getId())
                    .setDescription(m.getDescription())
                    .setCode(m.getCode())
                    .setName(m.getName())).collect(Collectors.toList()));
        });


        return Result.success(root);
    }


    @Operation(summary = "新增及更新",
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @PostMapping("/addAndUpdate")
    public Result addAndUpdate(@RequestBody @Validated DbTableInfoVo dbTableInfoVo, @RequestHeader(required = false) Integer appId) {
        LambdaQueryWrapper<DbTableInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(DbTableInfo::getName, dbTableInfoVo.getName()).last("limit 1");
        if (ObjUtil.isNotNull(appId)) {
            lambdaQuery.eq(DbTableInfo::getId, appId);
        }
        DbTableInfo isExist = dbTableInfoService.getOne(lambdaQuery);
        if (ObjUtil.isNull(dbTableInfoVo.getId()) && ObjUtil.isNotNull(isExist)) {
            throw new RuntimeException("实体Code已经存在，请修改!");
        }

        dbTableInfoVo.setAppId(appId);
        DbTableInfoVo tableInfoVo = dbTableInfoService.saveInfo(dbTableInfoVo);

        return Result.success(tableInfoVo);
    }

    @Operation(summary = "根据ID删除字段",
            parameters = {
                    @Parameter(name = "id", description = "ID")},
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/deleteById/{id}")
    public Result deleteById(@Valid @PathVariable Integer id) {
        dbTableFieldsInfoService.removeById(id);
        return Result.success();
    }

    @Operation(summary = "根据ID删除表，包含所有字段",
            parameters = {
                    @Parameter(name = "id", description = "ID")},
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/deleteAllById/{id}")
    public Result deleteAllById(@Valid @PathVariable Integer id) {
        dbTableInfoService.removeById(id);
        dbTableFieldsInfoService.remove(Wrappers.<DbTableFieldsInfo>lambdaQuery().eq(DbTableFieldsInfo::getTableId, id));
        return Result.success();
    }


    @Operation(summary = "根据表ID获取SQL",
            parameters = {
                    @Parameter(name = "id", description = "ID")},
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/getSqlByTable/{id}")
    public Result getSqlCreateByTable(@Valid @PathVariable Integer id) {
        DbTableInfo tableInfo = dbTableInfoService.getById(id);

        List<DbTableFieldsInfo> fieldsInfos = dbTableFieldsInfoService.list(Wrappers.<DbTableFieldsInfo>lambdaQuery().eq(DbTableFieldsInfo::getTableId, tableInfo.getId()));
        String createTableSQL = TableGeneratorUtils.generateCreateTableSQL(fieldsInfos, tableInfo.getName(), tableInfo.getNameCh());

        return Result.success(createTableSQL);
    }
}
